package com.yonyou.brigade.third_parties.tuniu.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.yonyou.brigade.basic_init.enums.ChannelEnum;
import com.yonyou.brigade.basic_init.service.IBriChannelService;
import com.yonyou.brigade.order_center.service.IBriOrderService;
import com.yonyou.brigade.third_parties.tuniu.constants.TuniuConstants;
import com.yonyou.brigade.third_parties.tuniu.model.TuniuConfig;
import com.yonyou.brigade.third_parties.tuniu.service.ITuniuOrderService;
import com.yonyou.brigade.third_parties.tuniu.utils.SignUtils;
import com.yonyou.brigade.util.resultutil.HttpSendUtils;
import com.yonyou.brigade.ybz.service.IConvertService;
import com.yonyou.ybzboot.starter.common.cipher.Base64Util;
import com.yonyou.ybzboot.starter.common.util.StringUtil;
import com.yonyou.ybzboot.starter.mongodb.dao.IMongoDao;
import com.yonyou.ybzboot.starter.mongodb.model.CriteriaMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
public class TuniuOrderServiceImpl implements ITuniuOrderService {

    Logger logger = LoggerFactory.getLogger(this.getClass());


    @Value("${tuniu.url}")
    private String tuniuBaseUrl;

    @Value("${tuniu.tradeFlightType}")
    private String tuniuFlightTradeType;

    @Value("${tuniu.tradeTrainType}")
    private String tuniuTrainTradeType;

    @Value("${tuniu.tradeHotelType}")
    private String tuniuHotelTradeType;

    @Value("${cnv.baigade.system.code}")
    private String systemCode;

    @Value("${cnv.register.userId}")
    private String cnvRegisterUserId;

    @Value("${cnv.register.tenant}")
    private String cnvRegisterTenant;

    @Value("${cnv.register.cookie}")
    private String cnvRegisterCookie;

    @Autowired
    @Qualifier("briChannelServiceImpl")
    private IBriChannelService briChannelService;

    @Autowired
    @Qualifier("convertServiceImpl")
    private IConvertService convertService;

    @Autowired
    @Qualifier("briOrderServiceImpl")
    private IBriOrderService briOrderService;

    @Autowired
    private IMongoDao mongoDao;


    @Override
    public void getTuniuOrderList(String tenant, String orgPk, String beginDate, String endDate, int page, int pageSize, int channelId) {
        Map paramsMap = new HashMap<>();
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        String timestamp = sdf.format(date);
        paramsMap.put("timestamp",timestamp);
        TuniuConfig channelConfig = (TuniuConfig) briChannelService.getChannelConfig(tenant, ChannelEnum.TUNIU.getName(), new TuniuConfig());
        String apiKey = null;
        String secretKey = null;
        String companyName = null;
        if (channelConfig != null) {
            apiKey = channelConfig.getApiKey();
            secretKey = channelConfig.getSecretKey();
            companyName = channelConfig.getCompanyName();
        }
        String sign = SignUtils.getSign(apiKey, secretKey, timestamp);
        paramsMap.put("sign",sign);
        paramsMap.put("apiKey",apiKey);
        if(!StringUtil.isEmpty("companyName")) {
            paramsMap.put("companyName", companyName);
        }
        JSONObject data = new JSONObject();
//        data.put("addTimeStart",beginDate);
//        data.put("addTimeEnd",endDate);
        data.put("startTime",beginDate);
        data.put("finishTime",endDate);
        data.put("pageSize",pageSize);
        String param = null;
        Boolean flag = true;
        while (flag) {
            data.put("page",page);
            paramsMap.put("data",data);
            if (!CollectionUtils.isEmpty(paramsMap)) {
                try {
                    param = Base64Util.encode(JSON.toJSONString(paramsMap));
                } catch (Exception e) {
                    logger.error("途牛Base64加密时，编码错误！",e);
                }
            }
            //获取订单编号
            String result = HttpSendUtils.sendGet(tuniuBaseUrl + TuniuConstants.URL_QUERYORDERLIST, param);
            if (!StringUtils.isEmpty(result)){
                try {
                    result = Base64Util.decode(result);
                } catch (Exception e) {
                    logger.error("途牛Base64解密时，编码错误！",e);
                }
            }
            JSONObject response = JSONObject.parseObject(result);
            if (response != null && response.size() > 0 && TuniuConstants.SUCCESS_CODE.equals(response.getString("code"))) {
                JSONObject dataReturn = response.getJSONObject("data");
                Integer count = dataReturn.getInteger("count");
                int pageCount = count / pageSize;
                //page到了最后一页结束循环
                if ((pageCount * pageSize == count && page >= pageCount) || page > pageCount) {
                    flag = false;
                }
                JSONArray rows = dataReturn.getJSONArray("rows");
                if (rows != null && rows.size() > 0) {
                    for (int i = 0; i < rows.size(); i++) {
                        Map paramsMapForOrderDetail = new HashMap<>();
                        JSONObject rowsJSONObject = rows.getJSONObject(i);
                        Date dateForOrderDetail = new Date();
                        String timestampForOrderDetail = sdf.format(dateForOrderDetail);
                        paramsMapForOrderDetail.put("timestamp",timestampForOrderDetail);
                        String signForOrderDetail = SignUtils.getSign(apiKey, secretKey, timestampForOrderDetail);
                        paramsMapForOrderDetail.put("sign",signForOrderDetail);
                        paramsMapForOrderDetail.put("companyName", companyName);
                        paramsMapForOrderDetail.put("apiKey",apiKey);
                        JSONObject dataForOrderDetail = new JSONObject();
                        String updateTime = rowsJSONObject.getString("updateTime");
//                        String orderId = rowsJSONObject.getString("orderId");
                        String orderId = rowsJSONObject.getString("listId");
                        dataForOrderDetail.put("orderId",orderId);
                        paramsMapForOrderDetail.put("data",dataForOrderDetail);
                        String paramForOrderDetail = null;
                        if (!CollectionUtils.isEmpty(paramsMapForOrderDetail)) {
                            try {
                                paramForOrderDetail = Base64Util.encode(JSON.toJSONString(paramsMapForOrderDetail));
                            } catch (Exception e) {
                                logger.error("途牛Base64加密时，编码错误！",e);
                            }
                        }
                        //通过订单编号获取订单详情
                        String resultForOrderDetail = HttpSendUtils.sendGet(tuniuBaseUrl + TuniuConstants.URL_QUERYORDERDETAIL, paramForOrderDetail);
                        if (!StringUtils.isEmpty(resultForOrderDetail)) {
                            try {
                                resultForOrderDetail = Base64Util.decode(resultForOrderDetail);
                            } catch (Exception e) {
                                logger.error("途牛Base64解密时，编码错误！",e);
                            }
                        }
                        JSONObject responseForOrderDetail = JSONObject.parseObject(resultForOrderDetail);
                        if (responseForOrderDetail != null && TuniuConstants.SUCCESS_CODE.equals(responseForOrderDetail.getString("code"))) {
                            JSONObject dataReturnForOrderDetail = responseForOrderDetail.getJSONObject("data");
                            if (dataReturnForOrderDetail != null) {
                                JSONObject orderBasic = dataReturnForOrderDetail.getJSONObject("orderBasic");
                                JSONObject newFlightDetailData = new JSONObject();
                                //下单人id
                                String operatorId = orderBasic.getString("operatorId");
                                //orderType: 1 国内火车票; 2 国内机票; 3 国内酒店; 5 国际机票
                                JSONObject res = new JSONObject();
                                if ((orderBasic.getInteger("orderType") == 2 || orderBasic.getInteger("orderType") == 5)) {
                                    JSONObject flightDetailData = dataReturnForOrderDetail.getJSONObject("flightDetailData");
                                    dealWithMongo(orderId, TuniuConstants.FLIGHT_MONGO_ORDER_TABLENAME, dataReturnForOrderDetail);
                                    //将航程信息放到订单详情中
                                    JSONArray journeyList = flightDetailData.getJSONArray("journeyList");
                                    //暂不支持多行程，若是多行程就先不存
                                    if (journeyList != null && journeyList.size() > 2) {
                                        continue;
                                    }
                                    if (journeyList != null && journeyList.size() > 0) {
                                        for (int j = 0; j < journeyList.size(); j++) {
                                            JSONObject journey = journeyList.getJSONObject(j);
                                            String journeyId = journey.getString("journeyId");
                                            //多航段时，只取第一个
                                            JSONArray segments = journey.getJSONArray("segments");
                                            if (segments != null && segments.size() > 0) {
                                                journey.put("segments",segments.get(0));
                                            } else {
                                                journey.put("segments",JSONObject.parseObject(""));
                                            }
                                            //将journeyId相同的price放到相应的journey中(一对一)
                                            JSONArray priceList = flightDetailData.getJSONArray("priceList");
                                            if (priceList != null && priceList.size() > 0) {
                                                for (int k = 0; k < priceList.size(); k++) {
                                                    if (journeyId != null && journeyId.equals(priceList.getJSONObject(k).getString("journeyId"))) {
                                                        journeyList.getJSONObject(j).put("priceList",priceList.getJSONObject(k));
                                                    }
                                                }
                                            }
                                        }
                                    }
                                    //将票信息放到订单详情中，与航程信息并列
                                    JSONArray ticketList = flightDetailData.getJSONArray("ticketList");
                                    JSONArray tickets = new JSONArray();
                                    List orgJourneyIdsReturn = null;
                                    List orgJourneyIdsEndorse = null;
                                    if (ticketList != null && ticketList.size() > 0) {
                                        for (int k = 0; k < ticketList.size(); k++) {
                                            JSONObject ticket = ticketList.getJSONObject(k);
                                            String partyId = ticket.getString("partyId");
                                            String journeyId = ticket.getString("journeyId");
                                            //每张票中还会有对应的退票和改签信息，用partyId(乘机人id)作为判断条件唯一确定某个人的退改签信息
                                            //退票信息
                                            JSONArray returnDetails = flightDetailData.getJSONArray("returnDetails");
                                            if (returnDetails != null && returnDetails.size() > 0) {
                                                for (int l = 0; l < returnDetails.size(); l++) {
                                                    JSONObject returnDetail = returnDetails.getJSONObject(l);
                                                    if ("1".equals(returnDetail.getString("result"))) { // 退票的操作结果为1，即操作成功
                                                        orgJourneyIdsReturn = (List)returnDetail.get("orgJourneyId");
                                                        String partyIdReturnDetail = returnDetail.getString("partyId");
                                                        if (partyId != null && partyId.equals(partyIdReturnDetail)) {
                                                            ticket.put("returnDetail",returnDetail);
                                                        }
                                                    }
                                                }
                                            }
                                            //改签信息
                                            JSONArray endorseDetails = flightDetailData.getJSONArray("endorseDetails");
                                            if (endorseDetails != null && endorseDetails.size() > 0) {
                                                for (int l = 0; l < endorseDetails.size(); l++) {
                                                    JSONObject endorseDetail = endorseDetails.getJSONObject(l);
                                                    if ("1".equals(endorseDetail.getString("result"))) { // 改签的操作结果为1，即操作成功
                                                        orgJourneyIdsEndorse = (List)endorseDetail.get("orgJourneyId");
                                                        String partyIdEndorseDetail = endorseDetail.getString("partyId");
                                                        if (partyId != null && partyId.equals(partyIdEndorseDetail)) {
                                                            ticket.put("endorseDetail",endorseDetail);
                                                        }
                                                    }
                                                }
                                            }
                                            //票信息对应的是订单中心的passenger信息，注意票号的保存机制：退票时不生成新的票号，而改签要生成新的票号，故需要保存新的票号
                                            JSONObject returnDetail = ticket.getJSONObject("returnDetail");
                                            JSONObject endorseDetail = ticket.getJSONObject("endorseDetail");
                                            //往返程
                                            if (journeyList != null && journeyList.size() == 2) {
                                                //无退改签or无改签但有退票
                                                if ((endorseDetail == null || endorseDetail.size() == 0) && ((returnDetail == null || returnDetail.size() == 0)
                                                        || (returnDetail != null && returnDetail.containsKey("partyId")
                                                        && !CollectionUtils.isEmpty(orgJourneyIdsReturn) && orgJourneyIdsReturn.contains(journeyId)))) {
                                                    for (int j = 0; j < journeyList.size(); j++) {
                                                        JSONObject journey = journeyList.getJSONObject(j);
                                                        String journeyId2 = journey.getString("journeyId");
                                                        if (!StringUtils.isEmpty(journeyId2) && journeyId2.equals(ticket.getString("journeyId"))) {
                                                            //去程
                                                            if (journey.getInteger("journeyNum") == 1) {
                                                                ticket.put("ticketId",ticket.getString("ticketId"));
                                                            //返程
                                                            } else if (journey.getInteger("journeyNum") == 2) {
                                                                ticket.put("ticketIdT",ticket.getString("ticketId"));
                                                            }
                                                        }
                                                    }
                                                //存在改签
                                                } else if (endorseDetail != null && endorseDetail.containsKey("partyId")
                                                        && !CollectionUtils.isEmpty(orgJourneyIdsEndorse) && orgJourneyIdsEndorse.contains(journeyId)) {
                                                    for (int j = 0; j < journeyList.size(); j++) {
                                                        JSONObject journey = journeyList.getJSONObject(j);
                                                        List<String> journeyIdListNew = (List<String>) endorseDetail.get("journeyId");
                                                        if (!CollectionUtils.isEmpty(journeyIdListNew)) {
                                                            for (int l = 0; l < journeyIdListNew.size(); l++) {
                                                                String journeyIdNew = journeyIdListNew.get(l);//改签之后的journeyId
                                                                if (!StringUtils.isEmpty(journeyIdNew) && journeyIdNew.equals(journey.getString("journeyId"))) {
                                                                    //去程改签
                                                                    if (journey.getInteger("journeyNum") == 1) {
                                                                        ticket.put("ticketId",ticket.getString("ticketId"));
                                                                    //返程改签
                                                                    } else if (journey.getInteger("journeyNum") == 2) {
                                                                        ticket.put("ticketIdT",ticket.getString("ticketId"));
                                                                    }
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            //单程
                                            } else if (journeyList != null && journeyList.size() == 1) {
                                                //无退改签or无改签但有退票
                                                if ((endorseDetail == null || endorseDetail.size() == 0) && ((returnDetail == null || returnDetail.size() == 0)
                                                        || (returnDetail != null && returnDetail.containsKey("partyId")
                                                        && !CollectionUtils.isEmpty(orgJourneyIdsReturn) && orgJourneyIdsReturn.contains(journeyId)))) {
                                                    JSONObject journey = journeyList.getJSONObject(0);
                                                    String journeyId2 = journey.getString("journeyId");
                                                    if (!StringUtils.isEmpty(journeyId2) && journeyId2.equals(ticket.getString("journeyId"))) {
                                                        ticket.put("ticketId",ticket.getString("ticketId"));
                                                    }
                                                //存在改签
                                                } else if (endorseDetail != null && endorseDetail.containsKey("partyId")
                                                        && !CollectionUtils.isEmpty(orgJourneyIdsEndorse) && orgJourneyIdsEndorse.contains(journeyId)) {
                                                    JSONObject journey = journeyList.getJSONObject(0);
                                                    List<String> journeyIdListNew = (List<String>) endorseDetail.get("journeyId");
                                                    String journeyIdNew = journeyIdListNew.get(0);
                                                    if (!StringUtils.isEmpty(journeyIdNew) && journeyIdNew.equals(journey.getString("journeyId"))) {
                                                        ticket.put("ticketId",ticket.getString("ticketId"));
                                                    }
                                                }
                                            }
                                            tickets.add(ticket);

                                        }
                                    }
                                    newFlightDetailData.put("ticketList",tickets);
                                    newFlightDetailData.put("journeyList",journeyList);

                                    newFlightDetailData.put("isInternational",flightDetailData.getString("isInternational"));
                                    newFlightDetailData.put("flightType",flightDetailData.getInteger("flightType"));
                                    newFlightDetailData.put("status",flightDetailData.getInteger("status"));
                                    dataReturnForOrderDetail.put("flightDetailData",newFlightDetailData);
                                    res = convertService.convert(tuniuFlightTradeType, systemCode, cnvRegisterUserId, cnvRegisterTenant, cnvRegisterCookie, dataReturnForOrderDetail);
                                } else if (orderBasic.getInteger("orderType") == 3) {
                                res = convertService.convert(tuniuHotelTradeType, systemCode, cnvRegisterUserId, cnvRegisterTenant, cnvRegisterCookie, dataReturnForOrderDetail);
                                } else if (orderBasic.getInteger("orderType") == 1) {
                                    dealWithMongo(orderId, TuniuConstants.TRAIN_MONGO_ORDER_TABLENAME, dataReturnForOrderDetail);
//                                  res = convertService.convert(tuniuTrainTradeType, systemCode, cnvRegisterUserId, cnvRegisterTenant, cnvRegisterCookie, dataReturnForOrderDetail);
                                } else {
                                    logger.info("该订单不是机票/酒店/火车票,所以不存到订单中心");
                                }
                                if (res != null && res.size() > 0 && res.getBoolean("success")) {
                                    JSONArray results = res.getJSONArray("result");
                                    if (results != null && results.size() > 0) {
                                        for (int j = 0; j < results.size(); j++) {
                                            JSONObject jsonObject = results.getJSONObject(j);
                                            JSONObject orderCenter = JSON.parseObject(jsonObject.getString("data"));
                                            if (orderCenter != null && orderCenter.size() > 0) {
                                                orderCenter.put("updateTime",updateTime);
                                                if (orderBasic.getInteger("orderType") == 2 || orderBasic.getInteger("orderType") == 5) {
                                                    try {
                                                        briOrderService.saveFlight(orderCenter, orderId, tenant, operatorId, ChannelEnum.TUNIU.getName(), channelId);
                                                    } catch (ParseException e) {
                                                        logger.error("保存途牛机票订单时，日期类型转换出现错误",e.getMessage());
                                                    }
                                                } else if (orderBasic.getInteger("orderType") == 3) {
                                                    try {
                                                        briOrderService.saveHotel(orderCenter, orderId, tenant, operatorId, ChannelEnum.TUNIU.getName(), channelId);
                                                    } catch (ParseException e) {
                                                        logger.error("保存途牛酒店订单时，日期类型转换出现错误",e.getMessage());
                                                    }
                                                } else if (orderBasic.getInteger("orderType") == 1) {
                                                     briOrderService.saveTrain(orderCenter, orderId, tenant, operatorId, ChannelEnum.TUNIU.getName(), channelId);
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            } else {
                flag = false;
            }
            page++;
        }
    }

    private void dealWithMongo(String orderId, String mongoName, JSONObject dataReturnForOrderDetail) {
        CriteriaMap criteriaMap = new CriteriaMap();
        criteriaMap.put("orderBasic.orderId",orderId);
        List<JSONObject> ordersources = mongoDao.findByMap(criteriaMap,JSONObject.class,mongoName);
        if(ordersources != null && ordersources.size() > 0) {
            mongoDao.deleteByMap(criteriaMap,mongoName);
            mongoDao.getMongoTemplate().save(dataReturnForOrderDetail,mongoName);
        }
        else {
            mongoDao.getMongoTemplate().insert(dataReturnForOrderDetail,mongoName);
        }
    }
}
